package factory;

import gameobject.Sprite;

import java.awt.Dimension;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;

import simulation.Game;

/**
 * Abstract Factory class for generation of sprites
 * it reads in a file to get information
 * it also generate sprites on special requests.
 *
 * @author Rex
 */
public abstract class Factory implements Runnable {

    private List<Sprite> mySprites;
    private Game myGame;
    private File myDataFile;
    private BufferedReader myReader = null;

    private boolean myIsActive;
    private int myTotalSprites;
    private int myCurrentNumber;
    private int myDelayTime;
    private Thread myThread;
    private Dimension myCanvasDimension;

    /**
     * Constructor for abstract Factory.
     * @param address name of file
     * @param delayTime delay
     * @param game which this Factory belongs to
     */
    public Factory(String address, int delayTime, Game game) {
        myGame = game;
        mySprites = game.getSpriteList();
        myCanvasDimension = game.getCanvasDimension();
        myDataFile = new File(address);
        myDelayTime = delayTime;

        try {
            myReader = new BufferedReader(new FileReader(myDataFile));
        }
        catch (FileNotFoundException e) {
            System.out.println("The path of the file is not correct");
            e.printStackTrace();
        }
        myIsActive = true;
        startGeneration();
        startThread();
    }

    protected void startThread() {
        myThread = new Thread(this);
        myThread.start();
    }

    protected void sleep() {
        try {
            myThread.sleep(myDelayTime);
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * This method can be overriden to apply
     * different ways of generating sprites.
     */
    protected abstract void startGeneration();

    @Override
    public void run() {
        while (myIsActive) {
            generateSprites();
            sleep();
        }
    }

    /**
     * Add sprites to the list; invoked in run().
     */
    protected abstract void generateSprites();

    /**
     * Stop this factory.
     */
    public void stop() {
        myIsActive = false;
    }

    protected String readNextLine() {
        if (myDataFile == null) {
            System.out.println("no file in this factory");
            return null;
        }
        try {
            String lineString = "";
            while ("".equals(lineString)) {
                lineString = myReader.readLine();
                //the current syntax format is that
                //anything in a line after "//" is ignored
                if (lineString.indexOf("//") >= 0) {
                    lineString = lineString.substring(
                            0, lineString.indexOf("//"));
                }
                lineString.trim();
            }
            return lineString;
        }
        catch (IOException e) {
            System.out.println("invalid file for generation: "
                    + myDataFile.getPath());
            e.printStackTrace();
            return null;
        }
    }

    protected abstract void instantiateByClassName(String info);

    /**
     * @return the delay time
     */
    public int getDelayTime() {
        return myDelayTime;
    }

    /**
     * Sets the delay time.
     * @param time to set
     */
    public void setDelayTime(int time) {
        myDelayTime = time;
    }

    /**
     * @return the dimensions of the canvas
     */
    public Dimension getCanvasDimension() {
        return myCanvasDimension;
    }

    /**
     * @return the game which this factory
     * belongs to
     */
    public Game getGame () {
        return myGame;
    }
}
